package com.chan.mediacamera.clip;

import android.annotation.TargetApi;
import android.app.NotificationManager;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaMuxer;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.chan.mediacamera.camera.media.MuxerWapper;
import com.chan.mediacamera.decoder.Decoder;
import com.chan.mediacamera.decoder.DecoderConfig;
import com.seu.magicfilter.filter.base.gpuimage.GPUImageFilter;
import com.seu.magicfilter.filter.helper.MagicFilterFactory;
import com.seu.magicfilter.filter.helper.MagicFilterType;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static android.media.MediaExtractor.SEEK_TO_PREVIOUS_SYNC;
import static com.chan.mediacamera.camera.media.MuxerWapper.DATA_AUDIO;
import static com.chan.mediacamera.camera.media.MuxerWapper.DATA_VIDEO;

/**
 * 重构
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class MediaClipper implements OnClipperListener {

    private final String TAG = MediaClipper.class.getSimpleName();

    private VideoClipper1 mVideoClipper;
    private AudioClipper mAudioClipper;
    private String mInputPath;
    private String mOutputPath;
    private int mOutputWidth;
    private int mOutputHeight;
    private int mVideoWidth;
    private int mVideoHeight;
    private int mVideoRotation;
    private long mVideoDuration;

    private MediaMuxer mMediaMuxer;
    private boolean mMuxerStarted;
    private boolean mVideoTrack;
    private boolean mAudioTrack;
    private byte[] mLock = new byte[0];

    private ExecutorService executorService = Executors.newFixedThreadPool(4);

    /**
     * 开始剪辑
     *
     * @param context
     * @param startPostion
     * @param clipDur
     */
    public void startClip(Context context, long startPostion, long clipDur) {
        try {
            mMediaMuxer = new MediaMuxer(mOutputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            ClipperConfig config = new ClipperConfig(context, mInputPath,
                    mOutputWidth, mOutputHeight, mVideoWidth, mVideoHeight);

            mVideoClipper = new VideoClipper1(this);
            mVideoClipper.startClip(config, startPostion, clipDur);

            mAudioClipper = new AudioClipper(this);
            mAudioClipper.startClip(config, startPostion, clipDur);

            executorService.submit(mVideoClipper);
            executorService.submit(mAudioClipper);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setOutputPath(String outputPath) {
        mOutputPath = outputPath;
    }

    public void setInputPath(String inputPath) {
        mInputPath = inputPath;
        MediaMetadataRetriever retr = new MediaMetadataRetriever();
        retr.setDataSource(mInputPath);
        String width = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
        String height = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
        String rotation = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
        String videoDuration = retr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        mVideoWidth = Integer.parseInt(width);
        mVideoHeight = Integer.parseInt(height);
        mVideoRotation = Integer.parseInt(rotation);
        mVideoDuration = Long.parseLong(videoDuration);
    }

    public void setOutputSize(int mOutputWidht, int mOutputHeight) {
        this.mOutputWidth = mOutputWidht;
        this.mOutputHeight = mOutputHeight;
    }

    @Override
    public void onStart(int dataStats) {
        if (dataStats == DATA_VIDEO) {
            Log.d("ttt", "mVideoTrack = true");
            mVideoTrack = true;
            mAudioTrack = true;
        } else if (dataStats == DATA_AUDIO) {
            Log.d("ttt", "mAudioTrack = true");
            mAudioTrack = true;
        }
        synchronized (mLock) {
            if (mAudioTrack && mVideoTrack) {
                mMediaMuxer.start();
                mMuxerStarted = true;
                mLock.notify();
            }
        }
    }

    @Override
    public void onStop(int dataStats) {
        Log.e("ttt", "onStop---" + dataStats);
        if (dataStats == MuxerWapper.DATA_VIDEO) {
            mVideoTrack = false;
            mAudioTrack = false;
        } else if (dataStats == MuxerWapper.DATA_AUDIO) {
            mAudioTrack = false;
        }
        Log.d("ttt", !mVideoTrack + "---" + !mAudioTrack);
        if (!mVideoTrack && !mAudioTrack) {
            if (mMediaMuxer != null) {
                mMediaMuxer.stop();
                mMediaMuxer.release();
                mMediaMuxer = null;
            }

            if (mVideoClipper != null) {
                mVideoClipper.release();
                mVideoClipper = null;
            }

            if (mAudioClipper != null) {
                mAudioClipper.release();
                mAudioClipper = null;
            }
        }
    }

    @Override
    public void onProcess(long currentPosition) {
        //Log.d("ttt", currentPosition + "---");
    }


    @Override
    public boolean isMuxStarted() {
        return mMuxerStarted;
    }

    @Override
    public int onFormatChanged(MediaFormat newFormat) {
        return mMediaMuxer.addTrack(newFormat);
    }

    @Override
    public void writeData(int mTrackIndex, ByteBuffer encodedData, MediaCodec.BufferInfo mBufferInfo) {
        synchronized (mLock) { // 锁进行mMediaMuxer.start();和writeSampleData互斥
            while (!mMuxerStarted) {
                try {
                    mLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        mMediaMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
    }

    public class ClipperConfig {
        String mPath;
        int mOutputWidth;
        int mOutputHeight;
        int mVideoWidth;
        int mVideoHeight;
        Context mContext;

        public ClipperConfig(Context context, String mPath, int outputWidth, int currentHeight, int videoWidth, int videoHeight) {
            this.mPath = mPath;
            this.mOutputWidth = outputWidth;
            this.mOutputHeight = currentHeight;
            this.mVideoWidth = videoWidth;
            this.mVideoHeight = videoHeight;
            this.mContext = context;
        }

        @Override
        public String toString() {
            return "ClipperConfig{" +
                    "mPath='" + mPath + '\'' +
                    ", mOutputWidth=" + mOutputWidth +
                    ", mOutputHeight=" + mOutputHeight +
                    ", mVideoWidth=" + mVideoWidth +
                    ", mVideoHeight=" + mVideoHeight +
                    ", mContext=" + mContext +
                    '}';
        }
    }
}
